#include "DMap.h"

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>

using namespace DeepClasses;

DeepClasses::DMap::DMap()
{
	m_cells=NULL;
	m_rows=0;
	m_cols=0;
	m_depth=0;
}

DeepClasses::DMap::~DMap()
{
	if(m_cells!=NULL)
	{
		ClearMap();
	}
}

int DeepClasses::DMap::GenerateMap(int z, int rows, int cols, std::list<DMaterial*>* mats)
{
	m_rows=rows;
	m_cols=cols;
	m_depth=z;

	if(m_cells!=NULL)
		ClearMap();

	DMaterial** stones = new DMaterial*[mats->size()];
	int stones_num = 0;
	BOOST_FOREACH(DMaterial* i, *mats)
	{
		if(i->m_class==L"stone")
		{
			stones[stones_num]=i;
			stones_num++;
		}
	}

	m_cells = new DCell**[m_depth];

	boost::mt19937 gen;
	boost::uniform_int<> dist(0, stones_num-1);
	boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
	

	for(int k=0;k<m_depth;k++)
	{
		m_cells[k] = new DCell*[m_rows];
		for(int i=0;i<m_rows;i++)
		{
			m_cells[k][i] = new DCell[m_cols];
			for(int j=0;j<m_cols;j++)
			{
				int level = m_depth/2;

				if(k<level)
					m_cells[k][i][j].m_fillMat=m_cells[k][i][j].m_floorMat=stones[die()];	
				else if(k==level)
					m_cells[k][i][j].m_floorMat=stones[die()];
				
			}
		}
	}


	return DE_OK;
}

int DeepClasses::DMap::ClearMap()
{
	for(int k=0;k<m_depth;k++)
	{
		for(int i=0;i<m_rows;i++)
		{
			delete [] m_cells[k][i];
		}
		delete [] m_cells[k];
	}

	delete [] m_cells;
	return DE_OK;
}

int DeepClasses::DMap::GetRows()
{
	return m_rows;
}

int DeepClasses::DMap::GetCols()
{
	return m_cols;
}

int DeepClasses::DMap::GetDepth()
{
	return m_depth;
}

wchar_t DeepClasses::DMap::GetSymbolAt( int k, int i, int j )
{
	if(m_cells[k][i][j].m_fillMat==NULL)
		return ' ';
	else
		return m_cells[k][i][j].m_fillMat->m_code;
}

DCell* DeepClasses::DMap::GetCellAt( int k, int i, int j )
{
	return &m_cells[k][i][j];
}

DCell* DeepClasses::DMap::GetCellAt( TLocation& loc )
{
	return GetCellAt(loc.m_z,loc.m_i,loc.m_j);
}

DCell* DeepClasses::DMap::GetCellAtShift( TLocation& loc, int k, int i, int j )
{
	if(loc.m_z+k>=0 && loc.m_z+k<m_depth && loc.m_i+i>=0 && loc.m_i+i<m_rows && loc.m_j+j>=0 && loc.m_j+j<m_cols)
		return GetCellAt(loc.m_z+k,loc.m_i+i,loc.m_j+j);
	else
		return NULL;
}